/*
 * CRSA.cpp
 *
 *  Created on: 2009-5-17
 *      Author: thh
 */

#include "RSA.h"
#include "SSLError.h"
#include "MemoryBIO.h"
#include <openssl/engine.h>
#include <stdexcept>

namespace Ybdj{
namespace Crypt{

	RSA::RSA(unsigned int bits,unsigned int e) {
		if(e % 2==0)
			throw std::invalid_argument("argument e must be an odd number");
		this->rsa = RSA_generate_key(bits,e,NULL,NULL);
		if(this->rsa==NULL)
			throw SSLError();
	}

	RSA::~RSA() {
		RSA_free(this->rsa);
	}

	bool RSA::Check()
	{
		if(RSA_check_key(this->rsa)!=1)
			throw SSLError();
		return true;
	}

	int RSA::Size()
	{
		return RSA_size(this->rsa);
	}

	int RSA::PublicEncrypt(int flen, unsigned char *from,unsigned char *to, Padding padding)
	{
		int ret = RSA_public_encrypt(flen,from,to,this->rsa,padding);
		if(ret==-1)
			throw SSLError();
		return ret;
	}
	int RSA::PublicDecrypt(int flen, unsigned char *from,unsigned char *to, Padding padding)
	{
		int ret = RSA_public_decrypt(flen,from,to,this->rsa,padding);
		if(ret==-1)
			throw SSLError();
		return ret;
	}
	int RSA::PrivateEncryt(int flen, unsigned char *from,unsigned char *to, Padding padding)
	{
		int ret = RSA_private_encrypt(flen,from,to,this->rsa,padding);
		if(ret==-1)
			throw SSLError();
		return ret;
	}
	int RSA::PrivateDecrypt(int flen, unsigned char *from,unsigned char *to, Padding padding)
	{
		int ret = RSA_private_decrypt(flen,from,to,this->rsa,padding);
		if(ret==-1)
			throw SSLError();
		return ret;
	}
	void RSA::Sign(Digest type, unsigned char *m, unsigned int m_len,unsigned char *sigret, unsigned int *siglen)
	{
		if(RSA_sign(type,m,m_len,sigret,siglen,this->rsa)==1)
			return;
		throw new SSLError();
	}
	bool RSA::Verify(Digest type, unsigned char *m, unsigned int m_len,unsigned char *sigbuf, unsigned int siglen)
	{
		if(RSA_verify(type,m,m_len,sigbuf,siglen,this->rsa)==1)
			return true;
		throw SSLError();
	}
	void  RSA::BlindingOn(BN_CTX *ctx)
	{
		if(RSA_blinding_on(this->rsa,ctx)==1)
			return;
		throw SSLError();
	}
	void RSA::BlindingOff(BN_CTX *ctx)
	{
		RSA_blinding_off(this->rsa);
	}

	std::string RSA::toString()
	{
		MemoryBIO bio;
		if(!RSA_print(bio,this->rsa,0)){
			return NULL;
		}
		char *txt = NULL;
		long len = bio.getData(&txt);

		std::string s(txt,len);
		return s;
	}
}
}
